package com.demo.modules.sys.controller;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.demo.common.base.R;
import com.demo.common.base.controller.BaseController;
import com.demo.common.exception.RRException;
import com.demo.common.utils.*;
import com.demo.modules.sys.entity.SysOssEntity;
import com.demo.modules.sys.form.SysOssQueryForm;
import com.demo.modules.sys.service.SysOssService;
import lombok.SneakyThrows;
import org.apache.commons.io.FileUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.FileCopyUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.*;

/**
 * 文件上传
 *
 */
@RestController
@RequestMapping("sys/oss")
public class SysOssController extends BaseController {

	@Autowired
	private SysOssService sysOssService;

	@Value("${fileupload.path}")
	private String path;

	/**
	 * 项目前缀
	 */
	@Value("${server.servlet.context-path}")
	private String serverPath;


	@GetMapping("/page")
	@RequiresPermissions("sys:oss:all")
	public R<PageUtils<SysOssEntity>> page(SysOssQueryForm params){
		PageUtils<SysOssEntity> page = sysOssService.queryPage(params);

		return R.ok(page);
	}

	@GetMapping("/list")
	public R<List<SysOssEntity>> list(SysOssQueryForm params){
		String idsStr = params.getIds() != null ? params.getIds() : "";
		List<String> ids = Arrays.asList(idsStr.split(","));

		List<SysOssEntity> list = sysOssService.list(new QueryWrapper<SysOssEntity>().lambda().in(CollectionUtil.isNotEmpty(ids), SysOssEntity::getId, ids));

		return R.ok(list);
	}

	@PostMapping("/delete")
	@RequiresPermissions("sys:oss:all")
	public R delete(@RequestBody Long[] ids){
		sysOssService.removeByIds(Arrays.asList(ids));

		return R.ok();
	}


	/**
	 * 上传文件
	 */
	@PostMapping("/upload")
	public R<SysOssEntity> upload(@RequestParam("file") MultipartFile file,String code,boolean isShrink) throws Exception {
		if (file.isEmpty()) {
			throw new RRException("上传文件不能为空");
		}

		//上传文件
		String suffix = Objects.requireNonNull(file.getOriginalFilename()).substring(file.getOriginalFilename().lastIndexOf("."));
		//保存文件信息
		SysOssEntity ossEntity = new SysOssEntity();

		uploadFile(file,code,isShrink,ossEntity);

		ossEntity.setFileName(file.getOriginalFilename());
		ossEntity.setFileSize(file.getSize());
		ossEntity.setFileSuffix(suffix);
		ossEntity.setContentType(file.getContentType());
		ossEntity.setCreator(ShiroUtils.getUserId());
		ossEntity.setCreateTime(new Date());
		sysOssService.save(ossEntity);

		return R.ok(ossEntity);
	}

	public void uploadFile(MultipartFile mpf,String code,boolean isShrink,SysOssEntity ossEntity){
		if(ObjectUtils.isEmpty(code)) {
			code = "";
		}
		//获取源文件名
		String originalFileName = mpf.getOriginalFilename();
		//生成新文件名称
		String newFileName = UUID.randomUUID().toString().replaceAll("-", "");
		//尾椎名称  如： .jpg
		String coccygealName = originalFileName.substring(originalFileName.indexOf("."));
		//新文件路径
		String newFilePath =  !ObjectUtils.isEmpty(code)? ("/upload/" + code +"/"+ DateUtils.format(new Date(), "yyyyMMdd")+"/") : ("/upload/"+ DateUtils.format(new Date(), "yyyyMMdd")+"/");

		try {
			//验证服务器存储路径是否存在，若不存在，则新建文件夹
			File serFile = new File(path + newFilePath);
			if (!serFile.exists()) {
				serFile.mkdirs();
			}
			//新文件路径
			String newPath = path + "/" + newFilePath + newFileName + coccygealName;
			//存储路径
			ossEntity.setPath(newFilePath + newFileName + coccygealName);
			ossEntity.setUrl(serverPath + newFilePath + newFileName + coccygealName);
			//将文件复制到文件服务器对应路径下
			FileCopyUtils.copy(mpf.getBytes(), new FileOutputStream(newPath));
			//生成缩列图
			if (isShrink) {

				//缩列图初始宽度
				int zoomWidth = ImageScale.ZOOM_WIDTH;
				//计算缩列图长宽
				BufferedImage bufferImage = ImageIO.read(new File(newPath));
				int width = bufferImage.getWidth();
				int height = bufferImage.getHeight();
				int zoomHeight = Math.round((float) height/width  * zoomWidth);

				//缩列图路径
				String shrinkPath = path + "/" + newFilePath + newFileName + "." + zoomWidth + "x" + zoomHeight + coccygealName;
				//存储路径
				ossEntity.setPath(newFilePath + newFileName +  "." + zoomWidth + "x" + zoomHeight + coccygealName);
				ossEntity.setUrl(serverPath + newFilePath + newFileName +  "." + zoomWidth + "x" + zoomHeight + coccygealName);
				//生成缩列图
				ImageScale.resizeFix(new File(newPath), new File(shrinkPath), zoomWidth, zoomHeight);
			}
		} catch (IOException e) {
			e.printStackTrace();
			throw new RRException("上传文件失败，请检查配置信息", e);
		}
	}

	/**
	 * 下载文件
	 */
	@GetMapping("/download/{fileId}/")
	@SneakyThrows
	public ResponseEntity<byte[]> download(@PathVariable("fileId") Long fileId) {
		SysOssEntity ossEntity = sysOssService.getById(fileId);

		File file = new File(path + ossEntity.getUrl());

		HttpHeaders headers = new HttpHeaders();
		//解决文件名中文乱码问题
		String downloadFileName = URLEncoder.encode(ossEntity.getFileName(), "utf-8");
		//告诉浏览器以"attachment"方式打开文件
		headers.setContentDispositionFormData("attachment", downloadFileName);
		//设置请求头的媒体格式类型为 application/octet-stream(二进制流数据)
		if (ObjectUtil.isNotEmpty(ossEntity.getContentType())) {
			headers.setContentType(MediaType.parseMediaType(ossEntity.getContentType()));
		} else {
			headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
		}
		// IE不支持CREATED(201)状态， 使用OK(200)
		return new ResponseEntity<>(FileUtils.readFileToByteArray(file),headers, HttpStatus.OK);
	}
}
